﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace myLittleC
{
    class UnaryExpression :IExpression  
    {

        IPartOfExpession[] Args = new IPartOfExpession[1];
	    
        public bool Postfix  { get; private set; } 
        
        public SubTokenType Operation { get; private set; }

        public IPartOfExpession[] Arguments { get { return Args; } private set { Args = value; } }
        public IPartOfExpession Argument { get { return Arguments[0]; } private set { Arguments[0] = value; } }

        public UnaryExpression(SubTokenType nOper, IPartOfExpession arg)
	    {
		    Operation = nOper;
             //if (!(arg is IPartOfExpession || arg is IExpression)) ну тут будет эксепшен
            Argument = arg;
            Postfix = false;
	    }

        public UnaryExpression(SubTokenType nOper, IPartOfExpession arg, bool iPostfix) :this(nOper, arg) 
        {   Postfix = iPostfix;}

        protected UnaryExpression(SubTokenType nOper,  IPartOfExpession[] Args)
        {
            Operation = nOper;
            Arguments = Args;
        }

        public override String ToString()
        {
            return Postfix ? String.Format(" {1}\n{0}", Argument.ToString("  "), Tokenizer.StringOperation(Operation))
                   : String.Format("{0}\n  {1}", Argument.ToString(" "), Tokenizer.StringOperation(Operation)); 
        }

        public virtual String ToString(String Shift)
        {
            return Postfix ? String.Format("{1}{2}\n{0}", Argument.ToString(Shift), Shift, Tokenizer.StringOperation(Operation))
                : String.Format("{0}\n{1}{2}", Argument.ToString(Shift + " "), Shift, Tokenizer.StringOperation(Operation)); 
        }
        public virtual String ToString(String prev, bool up)
        {
            String PrevLeft = (prev == "") ?  "  " : String.Format("{0}{1}     ", prev, (up ? " " : "│"));
            String PrevCenter = (prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"));

            String Left = Postfix ? String.Format("{0}┌────[{1}]", PrevLeft, Tokenizer.StringOperation(Operation)) : Argument.ToString(PrevLeft, true);
            String ce = Postfix ? Argument.ToString(prev, up) : String.Format("{0}[{1}]", PrevCenter, Tokenizer.StringOperation(Operation));
            return String.Format("{0}\n{1}│\n{2}", Left, PrevLeft, ce);
        }
        
    }

    class BinaryExpression :  UnaryExpression, IExpression
    {
        public IPartOfExpession Left { get { return Arguments[0]; } private set { Arguments[0] = value; } }
        public IPartOfExpession Right { get { return Arguments[1]; } private set { Arguments[1] = value; } }

        public BinaryExpression(SubTokenType nOper, IPartOfExpession nLeft, IPartOfExpession nRight)
            :base(nOper, new IPartOfExpession[2])
        {
            Left = nLeft;
            Right = nRight;
        }

        public bool IsLeft { get; private set; }

        public override String ToString()
        { return String.Format("{0}\n {1}\n{2}", Left.ToString("  "), Tokenizer.StringOperation(Operation), Right.ToString("  ")); }
        public override String ToString(String Shift)
        { return String.Format("{0}\n{1}{2}\n{3}", Left.ToString(Shift + " "), Shift, Tokenizer.StringOperation(Operation), Right.ToString(Shift + " ")); }

        public override String ToString(String prev, bool up)
        {
            String PrevLeft, PrevRight, PrevCenter;
            if (prev == "")
            {
                PrevCenter = " ";
                PrevRight = PrevLeft = "  ";
            }
            else
            {
                PrevLeft = String.Format("{0}{1}     ", prev, (up ? " " : "│"));
                PrevRight = String.Format("{0}{1}     ", prev, (up ? "│" : " "));
                PrevCenter = String.Format("{0}{1}────", prev, (up ? "┌" : "└"));
            }

            String SLeft = Left.ToString(PrevLeft, true);
            String SCenter = String.Format("{0}[{1}]", PrevCenter, Tokenizer.StringOperation(Operation));
            String SRight = Right.ToString(PrevRight, false);

            return String.Format("{0}\n{1}│\n{2}\n{3}│\n{4}", SLeft, PrevLeft, SCenter, PrevRight, SRight);
        }
    }
    class SyntaxConst : IPartOfExpession
    {
        public SubTokenType Type {get;  private set;}
        public Object Value{get;  private set;}

        public ExpType ExType { get; private set; }

        public SyntaxConst(Token iToken) { Type = iToken.SubType; Value = iToken.Value; }
	    
        public override String ToString() { return " "  + Value;}
        public String ToString(String Shift) { return Shift + Value;}

        public String ToString(String prev, bool up)
        { return String.Format("{0}|{1}|", ((prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"))), Value);}
    }
    

    class SyntaxVar : IPartOfExpession
    {
        public String Name {get ; private set;}
        public ExpType ExType { get; private set; }

        public SyntaxVar(String iName, ExpType iType) { Name = iName; ExType = iType; }
        public SyntaxVar(String iName) { Name = iName;}

        public override String ToString() { return " " + Name.ToString();}
        public String ToString(String Shift) { return Shift + Name.ToString();}

        public String ToString(String prev, bool up)
        { return String.Format("{0}|{1}|", ((prev == "") ? " " : String.Format("{0}{1}────", prev, (up ? "┌" : "└"))), Name); }
    };
}

